﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TriggerContextArgument.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   An <see cref="IArgument" /> that is evaluated in the context of the parameter supplied by a <see cref="TriggerBase" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Windows.Input
{
    using System;
    using System.Windows;
    using System.Windows.Data;

    /// <summary>
    ///   An <see cref = "IArgument" /> that is evaluated in the context of the parameter supplied by a <see cref = "TriggerBase" />
    /// </summary>
    /// <remarks>
    ///   The <see cref = "TriggerContextArgument" /> is most commonly used to extract values from the <see cref = "EventArgs" />
    ///   of an event trigger.
    /// </remarks>
    public class TriggerContextArgument : ArgumentBase
    {
        /// <summary>
        ///   Identifies the <see cref = "Binding" /> property.
        /// </summary>
        public static readonly DependencyProperty BindingProperty = DependencyProperty.Register("Binding", typeof(Binding),
            typeof(TriggerContextArgument), new PropertyMetadata(
                null, BindingPropertyChanged));

        [ThreadStatic] 
        private static readonly BindingEvaluator<object> BindingEvaluator = new BindingEvaluator<object>();

        /// <summary>
        ///   Gets or sets the binding.
        /// </summary>
        /// <value>The binding.</value>
        public Binding Binding
        {
            get { return (Binding)GetValue(BindingProperty); }
            set { SetValue(BindingProperty, value); }
        }

        protected override object Evaluate(object context)
        {
            return Binding != null ? BindingEvaluator.GetValueFromContext(context, Binding) : context;
        }

        private static void BindingPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            ((TriggerContextArgument)obj).BindingChanged();
        }

        private void BindingChanged()
        {
            // by applying the binding we make it immutable
            BindingEvaluator.ValueBinding = Binding;
            RaiseRequerySuggested();
        }

#if !SILVERLIGHT
        protected override Freezable CreateInstanceCore()
        {
            return new TriggerContextArgument();
        }
#endif
    }
}